home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / CommandNotFound / CommandNotFound.py < prev    next >
Encoding:
Python Source  |  2009-04-17  |  7.7 KB  |  177 lines

  1. # (c) Zygmunt Krynicki 2005, 2006, 2007, 2008
  2. # Licensed under GPL, see COPYING for the whole text
  3.  
  4. import sys, os, os.path, gdbm, posix, grp, string
  5. from util import gettext_wrapper as _
  6.  
  7. class BinaryDatabase:
  8.     def __init__(self, filename):
  9.         self.db = None
  10.         if filename.endswith(".db"):
  11.             try:
  12.                 self.db = gdbm.open(filename, "r")
  13.             except gdbm.error, err:
  14.                 print >>sys.stderr, "Unable to open binary database %s: %s" % (filename, err)
  15.     def lookup(self, key):
  16.         if self.db and self.db.has_key(key):
  17.             return self.db[key]
  18.         else:
  19.             return None
  20.  
  21. class FlatDatabase:
  22.     def __init__(self, filename):
  23.         self.rows = []
  24.         dbfile = file(filename)
  25.         for line in (line.strip() for line in dbfile):
  26.             self.rows.append(line.split("|"))
  27.         dbfile.close()
  28.     def lookup(self, column, text):
  29.         result = []
  30.         for row in self.rows:
  31.             if row[column] == text:
  32.                 result.append(row)
  33.         return result
  34.     def createColumnByCallback(self, cb, column):
  35.         for row in self.rows:
  36.             row.append(cb(row[column]))
  37.     def lookupWithCallback(self, column, cb, text):
  38.         result = []
  39.         for row in self.rows:
  40.             if cb(row[column],text):
  41.                 result.append(row)
  42.         return result
  43.  
  44. class ProgramDatabase:
  45.     (PACKAGE, BASENAME_PATH) = range(2)
  46.     def __init__(self, filename):
  47.         basename = os.path.basename(filename)
  48.         (self.arch, self.component) = basename.split(".")[0].split("-")
  49.         self.db = BinaryDatabase(filename)
  50.     def lookup(self, command):
  51.         result = self.db.lookup(command)
  52.         if result:
  53.             return result.split("|")
  54.         else:
  55.             return []
  56.  
  57. class CommandNotFound:
  58.     programs_dir = "programs.d"
  59.     prefixes = ("/bin", "/usr/bin", "/usr/local/bin", "/sbin", "/usr/sbin", "/usr/local/sbin", "/usr/games")
  60.     def __init__(self, data_dir=os.sep.join(('/','usr','share','command-not-found'))):
  61.         self.programs = []
  62.         p = os.path.join(data_dir, "priority.txt")
  63.         if os.path.exists(p):
  64.             self.priority_overrides = map(string.strip, open(p).readlines())
  65.         self.components = ['main','universe','contrib','restricted','non-free',
  66.                            'multiverse']
  67.         self.components.reverse()
  68.         self.sources_list = self._getSourcesList()
  69.         for filename in os.listdir(os.path.sep.join([data_dir, self.programs_dir])):
  70.             self.programs.append(ProgramDatabase(os.path.sep.join([data_dir, self.programs_dir, filename])))
  71.         try:
  72.             self.user_can_sudo = grp.getgrnam("admin")[2] in posix.getgroups()
  73.         except KeyError:
  74.             self.user_can_sudo = False
  75.     def getPackages(self, command):
  76.         result = set()
  77.         for db in self.programs:
  78.             result.update([(pkg,db.component) for pkg in db.lookup(command)])
  79.         return list(result)
  80.     def getBlacklist(self):
  81.         try:
  82.             blacklist = file(os.sep.join((os.getenv("HOME", "/root"), ".command-not-found.blacklist")))
  83.             return [line.strip() for line in blacklist if line.strip() != ""]
  84.         except IOError:
  85.             return []
  86.         else:
  87.             blacklist.close()
  88.     def _getSourcesList(self):
  89.         try:
  90.             import apt_pkg
  91.             from aptsources.sourceslist import SourcesList
  92.             apt_pkg.init()
  93.         except (SystemError, ImportError), e:
  94.             return []
  95.         sources_list = set([])
  96.         for source in SourcesList():
  97.              if not source.disabled and not source.invalid:
  98.                  for component in source.comps:
  99.                      sources_list.add(component)
  100.         return sources_list
  101.     def sortByComponent(self, x, y):
  102.         # check overrides
  103.         if (x[0] in self.priority_overrides and
  104.             y[0] in self.priority_overrides):
  105.             # both have priority, do normal sorting
  106.             pass
  107.         elif x[0] in self.priority_overrides:
  108.             return -1
  109.         elif y[0] in self.priority_overrides:
  110.             return 1
  111.         # component sorting
  112.         try:
  113.             xidx = self.components.index(x[1])
  114.         except:
  115.             xidx = -1
  116.         try:
  117.             yidx = self.components.index(y[1])
  118.         except:
  119.             xidx = -1
  120.         return (yidx-xidx) or cmp(x,y)
  121.     def advise(self, command, ignore_installed=False):
  122.         def _in_prefix(prefix, command):
  123.             " helper that returns if a command is found in the given prefix "
  124.             return (os.path.exists(os.path.join(prefix, command)) and 
  125.                     not os.path.isdir(os.path.join(prefix, command)))
  126.  
  127.         if command.startswith("/"):
  128.             if os.path.exists(command):
  129.                 prefixes = [os.path.dirname(command)]
  130.             else:
  131.                 prefixes = []
  132.         else:
  133.             prefixes = [prefix for prefix in self.prefixes if _in_prefix(prefix, command)]
  134.         if prefixes and not ignore_installed:
  135.             if len(prefixes) == 1:
  136.                 print >>sys.stderr, _("Command '%(command)s' is available in '%(place)s'") % {"command": command, "place": os.path.join(prefixes[0], command)}
  137.             else:
  138.                 print >>sys.stderr, _("Command '%(command)s' is available in the following places") % {"command": command}
  139.                 for prefix in prefixes:
  140.                     print >>sys.stderr, " * %s" % os.path.join(prefix, command)
  141.             missing = list(set(prefixes) - set(os.getenv("PATH", "").split(":")))
  142.             if len(missing) > 0:
  143.                 print >>sys.stderr, _("The command could not be located because '%s' is not included in the PATH environment variable.") % ":".join(missing)
  144.                 if "sbin" in ":".join(missing):
  145.                     print >>sys.stderr, _("This is most likely caused by the lack of administrative priviledges associated with your user account.")
  146.             return False
  147.         if command in self.getBlacklist():
  148.             return False
  149.         packages = self.getPackages(command)
  150.         if len(packages) == 1:
  151.             print >>sys.stderr, _("The program '%s' is currently not installed. ") % command,
  152.             if posix.geteuid() == 0:
  153.                 print >>sys.stderr, _("You can install it by typing:")
  154.                 print >>sys.stderr, "apt-get install %s" %  packages[0][0]
  155.             elif self.user_can_sudo:
  156.                 print >>sys.stderr, _("You can install it by typing:")
  157.                 print >>sys.stderr, "sudo apt-get install %s" %  packages[0][0]
  158.             else:
  159.                 print >>sys.stderr, _("To run '%(command)s' please ask your administrator to install the package '%(package)s'") % {'command': command, 'package': packages[0][0]}
  160.             if not packages[0][1] in self.sources_list:
  161.                 print >>sys.stderr, _("You will have to enable the component called '%s'") % packages[0][1]
  162.         elif len(packages) > 1:
  163.             packages.sort(self.sortByComponent)
  164.             print >>sys.stderr, _("The program '%s' can be found in the following packages:") % command
  165.             for package in packages:
  166.                 if package[1] in self.sources_list:
  167.                     print >>sys.stderr, " * %s" % package[0]
  168.                 else:
  169.                     print >>sys.stderr, " * %s" % package[0] + " (" + _("You will have to enable component called '%s'") % package[1] + ")"
  170.             if posix.geteuid() == 0:
  171.                 print >>sys.stderr, _("Try: %s <selected package>") % "apt-get install"
  172.             elif self.user_can_sudo:
  173.                 print >>sys.stderr, _("Try: %s <selected package>") % "sudo apt-get install"
  174.             else:
  175.                 print >>sys.stderr, _("Ask your administrator to install one of them")
  176.         return len(packages) > 0
  177.